/*
 * tick.c
 *
 *  Created on: 2021-12-10
 *      Author: chenss
 */

#include "tick.h"

#define TIMx TIMER0
#define TIMx_IRQn TMR0_IRQn
#define TIMx_IRQHandler TMR0_IRQHandler

#define TIM_FREQ 100
#define TIM_INTERVAL (1000 / TIM_FREQ)

//#define TIM_CLK TIMER_GetModuleClock(TIMx)

// 毫秒计数
static Tick_t _milliseconds;

static uint32_t _msInterval, _usInterval;

void Tick_Init(void)
{
    uint32_t freq;
    uint32_t cnt_clk;
    uint32_t tim_clk = TIMER_GetModuleClock(TIMx);

    freq = TIMER_Open(TIMx, TIMER_PERIODIC_MODE, TIM_FREQ);
    assert(freq == TIM_FREQ);
    ON_RELEASE(UNUSED(freq);)

    cnt_clk = tim_clk / ((TIMx->CTL & TIMER_CTL_PSC_Msk) + 1);
    //debug("CNT_CLK: %lu\n", CNT_CLK);
    _milliseconds = 0;
    _msInterval = cnt_clk / 1000UL;    // 定时器计数器每毫秒增加的数值
    _usInterval = cnt_clk / 1000000UL; // 定时器计数器每微秒增加的数值

    TIMER_EnableInt(TIMx);
    Main_SetPriority(TIMx_IRQn, 0, 0);
    NVIC_EnableIRQ(TIMx_IRQn);
    TIMER_Start(TIMx);
}

void TIMx_IRQHandler(void)
{
    if(TIMER_GetIntFlag(TIMx))
    {
        TIMER_ClearIntFlag(TIMx);

        _milliseconds += TIM_INTERVAL;
    }
}

static inline Tick_t _Milliseconds(void)
{
    Tick_t ms;
    uint32_t cnt;

    do
    {
        ms = _milliseconds;
        cnt = TIMER_GetCounter(TIMx);
    }while(ms != _milliseconds);

    return ms + (cnt / _msInterval);
}

/**
 *
 * @return 毫秒数
 */
Tick_t Tick_Milliseconds(void)
{
    return _Milliseconds();
}

uint64_t HAL_GetTick(void)
{
    return (uint64_t)_Milliseconds();
}

/**
 *
 * @return 微秒数
 */
Tick_t Tick_Microseconds(void)
{
    Tick_t ms;
    uint32_t cnt;

    do
    {
        ms = _milliseconds;
        cnt = TIMER_GetCounter(TIMx);
    }while(ms != _milliseconds);

    return (ms * 1000) + (cnt / _usInterval);
}

uint32_t Tick_Seconds(void)
{
    return (uint32_t)(_milliseconds / 1000);
}

void Tick_DelayMicroseconds(uint32_t us)
{
    Tick_t now = Tick_Microseconds();
    Tick_t target = now + us;

    while(now < target)
    {
        now = Tick_Microseconds();
    }
}
